package domain.model.project.support;

import domain.model.project.*;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

import java.util.List;

/**
 * @author Gregory Boissinot
 */
public class ProjectImpl implements RWProject {

    private final ProjectId projectId;
    private final ProjectStatus projectStatus;

    private ProjectType projectType;
    private ProjectSCM projectSCM;
    private String description;
    private String templateLocalFilePath;

    public ProjectImpl(ProjectId projectId, ProjectStatus projectStatus) {
        this.projectId = projectId;
        this.projectStatus = projectStatus;
    }

    @Override
    public ProjectId getProjectId() {
        return projectId;
    }

    @Override
    public ProjectSCM getProjectSCM() {
        return projectSCM;
    }

    @Override
    public void setProjectSCM(ProjectSCM projectSCM) {
        this.projectSCM = projectSCM;
    }

    @Override
    public ProjectStatus getStatus() {
        return projectStatus;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public ProjectType getProjectType() {
        return projectType;
    }

    @Override
    public void setProjectType(ProjectType projectType) {
        this.projectType = projectType;
    }

    @Override
    public String getTemplateLocalFilePath() {
        return templateLocalFilePath;
    }

    @Override
    public void setTemplateLocalFilePath(String templateLocalFilePath) {
        this.templateLocalFilePath = templateLocalFilePath;
    }

    @Override
    public Project copyWithNewProjectSCM(ProjectSCM projectSCM) {
        return new ProjectBuilder(getProjectId().getOrganization(), getProjectId().getName(), getStatus())
                .projectType(getProjectType())
                .projectSCM(projectSCM)
                .description(getDescription())
                .build();
    }

    @Override
    public Project copyWithNewProjectDevelopers(List<ProjectDeveloper> projectDeveloperList) {
        final ProjectType projectType = getProjectType();
        if (projectType instanceof BuildProjectType) {
            final BuildProjectType buildProjectType = (BuildProjectType) projectType;
            ProjectType newProjectType = buildProjectType.copyWithProjectDevelopers(projectDeveloperList);
            return new ProjectBuilder(getProjectId().getOrganization(), getProjectId().getName(), getStatus())
                    .projectType(newProjectType)
                    .projectSCM(getProjectSCM())
                    .description(getDescription())
                    .build();
        }
        throw new IllegalStateException("You can update only a build project with developers.");
    }

    @Override
    public Project copyWithNewStatus(ProjectStatus projectStatus) {
        return new ProjectBuilder(getProjectId().getOrganization(), getProjectId().getName(), projectStatus)
                .projectType(getProjectType())
                .projectSCM(getProjectSCM())
                .description(getDescription())
                .build();
    }

    @Override
    public boolean sameEntityAs(Project entity) {
        return equals(entity);
    }

    @Override
    public String toString() {
        final ReflectionToStringBuilder reflectionToStringBuilder = new ReflectionToStringBuilder(this,
                ToStringStyle.MULTI_LINE_STYLE);
        return reflectionToStringBuilder.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ProjectImpl project = (ProjectImpl) o;

        if (description != null ? !description.equals(project.description) : project.description != null) return false;
        if (projectId != null ? !projectId.equals(project.projectId) : project.projectId != null) return false;
        if (projectSCM != null ? !projectSCM.equals(project.projectSCM) : project.projectSCM != null) return false;
        if (projectStatus != project.projectStatus) return false;
        if (projectType != null ? !projectType.equals(project.projectType) : project.projectType != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = projectId != null ? projectId.hashCode() : 0;
        result = 31 * result + (projectStatus != null ? projectStatus.hashCode() : 0);
        result = 31 * result + (projectType != null ? projectType.hashCode() : 0);
        result = 31 * result + (projectSCM != null ? projectSCM.hashCode() : 0);
        result = 31 * result + (description != null ? description.hashCode() : 0);
        return result;
    }
}
